<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>
  <!-- 
    ajax: async javascript and xml 与后端交互的一种工具 获取数据的艺术

    数据分离：
      前端写模板 然后单独加载数据(通过后端的接口获取后端服务器的数据) 

      接口：API 给前端访问获取数据的入口(函数 方法 某些功能)

    xml: 描述的数据
      比如一个人：
      <person>
        <name>张三</name>
        <age>18</age>
      </person>

      这是一种很古老的描述数据的结构，
      用于存储或者传输数据；

    现在版本的数据格式：json JavaScript 对象的数据格式 数据结构

    比如：
    {
      "name": "张三"，
      "age": 18,
      "list": [1,2,3]
    }
    JSON 格式非常严格 属性名都采用 双引号 字符串也采用双引号 不允许有多余标点符号

    将 js 对象转化为 JSON字符串： JSON.stringify(obj)

    将 JSON字符串 转化为 js 对象： JSON.parse(jsonStr)

    JSON里面不能存放函数；

    目前的开发都是前后端分离式，可并发进行开发；
    未来随着硬件技术和网络技术的提升，前端工程化会越来越精细，越来越庞大
    伴随着 node.js 的出现，使得前端有了自己的后台服务，使得前端的运行环境大大提升，不再局限于浏览器

    ajax 对象： 一个可以向后台发送请求的对象
      JS 向后台发送请求；

      XMLHttpRequest 对象
        接口都是对外公开的

      如何发起一个 GET 请求

        1.new XMLHttpRequest()
        2.对 ajax 对象进行一些初始化操作 open()
          2.1 请求方法： 以 restful 规范设计接口；
            GET： 从服务器获取数据；
            POST： 将数据发送给服务器；

            后续的请求都被阻止了
            OPTIONS：查看服务器的性能
            HEAD： 获取报头
            DELETE： 删除资源
            PUT： 更新资源
            TRACE：用于测试或者诊断
          2.2 地址： 服务器能访问的位置： https://www.baidu.com:8080/imgae/list?page=2&length=10
              服务器的实际地址 其实是 ip 地址 上述只是主机的域名 
              ip 地址：172.0.0.1 
              域名相当于 IP 地址的别名 方便记忆和操作 域名需要申请和备案的；

              协议 + 域名 + 端口 + 路由 + 请求字段
          3. 发送请求：send()

          常见问题： 跨域 即不允许跨域请求资源
            什么是同源？ 即 协议名 域名 端口都相同，也叫同域下的资源
            http://www.baidu.com
            https://www.baidu.com 这就是两个不同的源

            解决方法：
              跨域是浏览器的问题，出于安全考虑，浏览器会阻止跨域请求；
              1.将浏览器禁用跨域检测，但是此方法仅限本地测试，无法禁用用户的浏览器；
              2.后台设置请求头，允许跨域；CORS 跨域资源共享 目前的主流方法
              3.使用 JSONP 方法绕过同源检测；

          4.响应处理 onreadystatechange = function(){
            if(readState === 4){
              if(status >= 200 && status < 300 || status === 304){
                获取 responseText
              }
            }
          }
            readyState: 
              ajax 对象的状态 一共有五个
              0：ajax 对象初始化完成，但是没有做请求配置
              1：进行基础配置
              2：发送请求 这是一个异步操作
              3：服务器正在处理
              4：接收到服务器的返回状态

            请求状态吗：
              100 ~ 600
              100+：表示未完成，一般不用
              200+：表示请求成功，只是成功方式有差别
              300+：重定向 尤其 304 表示 Not Modified
              400+: 一般情况下表示 请求错误 多半是客户端的错误 比如无权限，地址出错等等 403 拒绝请求，404 找不到资源；
              500+：服务器错误 导致无法获取数据

            然后根据状态码来进行操作；

            成功即可获取返回字段
            responseText

            const xhr = new XMLHttpRequest()
            xhr.open('get',url + data) // 可携带数据
            xhr.send(null)
            xhr.onreadystatechange = function(){
              if(xhr.readyState === 4){
              if(xhr.status >= 200 && xhr.status < 300 || xhr.status===304){ 
                处理 xhr.responseTetx 
              }
            }

            后端(Node.js) 使用 express 模块当中 的 app.get(数据源地址，回调函数(req,res)=>{}) 来处理

      发起一个 POST 请求：
          与 GET 请求大同小异
          const xhr = new XMLHttpRequest()
          xhr.open('post',url) // 不需要携带数据

          与 GET 不同的地方

          xhr.setRequestHeader('content-type','application/x-www-form-urlencoded')  这是一种 form 格式
          xhr.send(a=1&b=2) 数据发送需要以这种格式发送

          后端就需要 使用 body-parser 模块当中的 
          app.use(bodyParser.urlencoded({
            extended: true
          })) 来进行解码

          xhr.setRequestHeader('content-type','application/json') 这是另一种格式 JSON格式
          xhr.send(JSON.stringify({a:1,b:2})) 数据发送需要将对象转化为 JSON 字符流

          后端就需要 使用 body-parser 模块当中的
          app.use(bodyParser.json()) 来进行解码

          然后使用 express 模块中的 app.post() 处理

          前端则 在 xhr.onreadystatechange = function(){
            if(xhr.readyState === 4){
              if(xhr.status >= 200 && xhr.status < 300 || xhr.status === 304){
                处理 xhr.responseTetx
              }
            }
          }

      跨域问题：
          1.关闭本地浏览器的预检机制，不推荐使用；
          2.在请求头中设置 允许跨域请求：
            app.use((req,res,next)=>{
              res.header({
              'Access-Control-Allow-Origin': '*',
              'Access-Control-Allow-Methods': '*',
              'Access-Control-Allow-Headers': '*'
              })
              next()
            })

            同时，还需要处理 浏览器发起的 预检请求 也需要设置同样的请求头
            app.options(数据源地址, function (req, res, next) {
              res.header({
                'Access-Control-Allow-Origin': '*',
                'Access-Control-Allow-Methods': '*',
                'Access-Control-Allow-Headers': '*'
              })
              next()
            })
            之后便可以该资源就支持跨域请求了
          3.JSONP 处理：JSON with padding 后端将数据包裹起来发送给前端
            script 标签可以跨域请求资源

            假设前端有一个函数 getData 可以拿到数据
            然后后端通过 app.get('/jsonp',(req,res)=>{
              const fn = req.query.cb 后端拿到函数名

              let data = JSON.stringify({name:'datafromjsonp'}) 假设后端拿到数据

              res.send(`${fn}(${data})`) 返回函数名和数据在前端当中执行函数
            })

            前端则创建一个 script 标签 通过 script.src = '协议//域名：端口/jsonp?cb=getData' 来发起请求
            

-->

  <script src="./index.js"></script>

</body>

</html>